package pl.edu.agh.nn.backpropagation;

import java.util.ArrayList;

import pl.edu.agh.nn.conf.InvalidNetworkConfigurationException;
import pl.edu.agh.nn.layer.AbstractLayer;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("Layer")
public class BackPropagationLayer extends AbstractLayer<BackPropagationNeuron> {

	private double learningSpeed = 0.1;
	private double momentum = 0.1;
	private boolean biasConnected = false;

	@Override
	public void configure() throws InvalidNetworkConfigurationException {
		if (activation == null) {
			throw new InvalidNetworkConfigurationException();
		}
		if (((neurons == null) || neurons.isEmpty())) {
			if (neuronCount < 1) {
				throw new InvalidNetworkConfigurationException();
			} else {
				neurons = new ArrayList<BackPropagationNeuron>();
				for (int i = 0; i < neuronCount; i++) {
					BackPropagationNeuron neuron = new BackPropagationNeuron();
					neuron.setActivation(activation);
					neuron.setMomentum(momentum);
					neuron.setLearningSpeed(learningSpeed);
					neuron.createSynapses(getPreviousLayer().getNeurons());
					neurons.add(neuron);
				}
			}
		} else {
			neuronCount = neurons.size();
			for (BackPropagationNeuron neuron : neurons) {
				if ((neuron.getSynapses() == null) || neuron.getSynapses().isEmpty()) {
					neuron.createSynapses(getPreviousLayer().getNeurons());
				}
				if (neuron.getLearningSpeed() == 0) {
					neuron.setLearningSpeed(learningSpeed);
				}
				if (neuron.getMomentum() == 0) {
					neuron.setMomentum(momentum);
				}
				if (neuron.getActivation() == null) {
					neuron.setActivation(activation);
				}
			}
		}
	}

	public double getLearningSpeed() {
		return learningSpeed;
	}

	public double getMomentum() {
		return momentum;
	}

	public void setLearningSpeed(double learningSpeed) {
		this.learningSpeed = learningSpeed;
	}

	public void setMomentum(double momentum) {
		this.momentum = momentum;
	}

	public void setBiasConnected(boolean biasConnected) {
		this.biasConnected = biasConnected;
	}

	public boolean isBiasConnected() {
		return biasConnected;
	}

}
